package com.ebupt.migu.music.common.util;

import com.alibaba.fastjson.JSONArray;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * Created by Intellij IDEA.
 * User:  liuyangyang@cd.ebupt.com
 * Date:  2019/10/23
 */
@Slf4j
public class HttpUtils {
    private static PoolingHttpClientConnectionManager connMgr;
    private static RequestConfig requestConfig;
    private static final int MAX_TIMEOUT = 10000;
    // 线程安全的
    private static CloseableHttpClient httpClient;

    static {
        // 设置连接池
        connMgr = new PoolingHttpClientConnectionManager();
        connMgr.setMaxTotal(500);
        connMgr.setDefaultMaxPerRoute(10);

        RequestConfig.Builder configBuilder = RequestConfig.custom();
        // 设置链接超时
        configBuilder.setConnectTimeout(MAX_TIMEOUT);
        // 设置读取超时
        configBuilder.setSocketTimeout(MAX_TIMEOUT);
        // 设置从连接池获取连接实例的超时
        configBuilder.setConnectionRequestTimeout(MAX_TIMEOUT);
        requestConfig = configBuilder.build();
        httpClient = HttpClients.custom().setConnectionManager(connMgr).build();
    }

    public static String doGetRequest(String url, Map<String, Object> map) {
        List<NameValuePair> params = new ArrayList<>();
        Set<Entry<String, Object>> set = map.entrySet();
        for (Entry<String, Object> entry : set) {
            NameValuePair nameValuePair = new BasicNameValuePair(entry.getKey(), (String) entry.getValue());
            params.add(nameValuePair);
        }
        String apiURL = url;
        log.info("访问URL：{}，访问参数：{}", url, map.toString());
        String result = null;
        try {
            String str = EntityUtils.toString(new UrlEncodedFormEntity(params, Consts.UTF_8));
            HttpGet httpGet = new HttpGet(apiURL + "?" + str);
            HttpResponse response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            if (null != entity) {
                InputStream inputStream = entity.getContent();
                result = IOUtils.toString(inputStream, "UTF-8");
            }
            EntityUtils.consume(entity);
        } catch (IOException io) {
            throw new RuntimeException("调用远程URL连接失败", io);
        }
        log.info("访问URL：{}， 访问结果：{}", url, result);
        return result;
    }

    /**
     * 发送HTTP POST请求: JSON
     *
     * @param apiUrl
     * @param json
     * @param header
     * @return
     * @throws IOException
     */
    public static String doPost(String apiUrl, Object json, Map<String, String> header) throws IOException {
        String httpStr = null;
        HttpPost httpPost = new HttpPost(apiUrl);
        CloseableHttpResponse response = null;
        httpPost.setConfig(requestConfig);
        if (null != header) {
            Set<Entry<String, String>> set = header.entrySet();
            for (Entry<String, String> entry : set) {
                httpPost.setHeader(entry.getKey(), entry.getValue());
            }
        }
        // 防止中文乱码
        StringEntity stringEntity = new StringEntity(json.toString(), "UTF-8");
        stringEntity.setContentEncoding("UTF-8");
        stringEntity.setContentType("application/json");
        httpPost.setEntity(stringEntity);
        response = httpClient.execute(httpPost);
        if (null == response) {
            throw new RuntimeException("response对象为空");
        }
        HttpEntity entity = response.getEntity();
        httpStr = EntityUtils.toString(entity, "UTF-8");
        if (null != response) {
            EntityUtils.consume(response.getEntity());
        }
        return httpStr;
    }


    /**
     * 没有header的post请求
     *
     * @param apiUrl
     * @param object
     * @return
     */
    public static String doPost(String apiUrl, Object object) {
        log.info("URL:{}, params:{}", apiUrl, object);
        CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build();
        String httpStr = null;
        HttpPost httpPost = new HttpPost(apiUrl);
        CloseableHttpResponse response = null;
        try {
            httpPost.setConfig(requestConfig);
            if (null == object) {
                log.info("params is empty");
            }
            //  String json = JsonUtils.obj2Json(params);
            String json = JSONArray.toJSON(object).toString();
            log.info("发送JSON体:{}", json);
            StringEntity entitys = new StringEntity(json, "UTF-8");
            entitys.setContentType("application/json");
            httpPost.setEntity(entitys);
            response = httpClient.execute(httpPost);
            if (null == response) {
                throw new RuntimeException("response对象为空");
            }
            HttpEntity entity = response.getEntity();
            httpStr = EntityUtils.toString(entity, "UTF-8");
            if (null != response) {
                EntityUtils.consume(response.getEntity());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            closeResponse(response);
        }
        return httpStr;
    }

    private static void closeResponse(CloseableHttpResponse response) {
        if (response != null) {
            try {
                EntityUtils.consume(response.getEntity());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 发送xml数据请求到server端
     *
     * @param url     xml请求数据地址
     * @param xmlInfo 发送的xml数据流
     * @return null发送失败，否则返回响应内容
     */
    public static String posts(String url, String xmlInfo, Map<String, String> params) {
        //  创建 HttpClient
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //  post 请求
        HttpPost httpPost = new HttpPost(url);
        //  返回值
        CloseableHttpResponse response;
        String content = null;
        try {
            HttpEntity httpEntity = new StringEntity(xmlInfo);
            httpPost.setEntity(httpEntity);
            if (params.size() > 0) {
                Set<Entry<String, String>> set = params.entrySet();
                for (Entry<String, String> entry : set) {
                    log.info("传入的请求头key:{},value:{}", entry.getKey(), entry.getValue());
                    httpPost.addHeader(entry.getKey(), entry.getValue());
                }
            }
            response = httpClient.execute(httpPost);
            int code = response.getStatusLine().getStatusCode();
            log.info("请求返回的code:{}" + code);
            if (code == 200) {
                HttpEntity entity = response.getEntity();
                content = EntityUtils.toString(entity, "UTF-8");
                if (null != response) {
                    EntityUtils.consume(response.getEntity());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return content;
    }

    /**
     * 发送xml数据请求到server端
     *
     * @param url    xml请求数据地址
     * @param buffer 数据流
     * @return null发送失败，否则返回响应内容
     */
    public static String postStream(String url, byte[] buffer, Map<String, String> params) throws IOException {
        //  创建 HttpClient
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //  post 请求
        HttpPost httpPost = new HttpPost(url);
        //  返回值
        CloseableHttpResponse response;
        String content = null;
        try {
            /* MultipartEntityBuilder builder = MultipartEntityBuilder.create();
             *//*绑定文件参数，传入文件流和contenttype，此处也可以继续添加其他formdata参数*//*
            String name=fileName.substring(0,fileName.indexOf("."));
            log.info("获取name:{},文件名fileName:{},上传字节数length:{}",name,fileName,buffer.length);

            builder.addBinaryBody("name",sbs, ContentType.MULTIPART_FORM_DATA,fileName);*/
            log.info("buffer:{}", buffer.length);
            InputStreamEntity inputStreamEntity = new InputStreamEntity(new ByteArrayInputStream(buffer), buffer.length);
            httpPost.setEntity(inputStreamEntity);
            if (params.size() > 0) {
                Set<Entry<String, String>> set = params.entrySet();
                for (Entry<String, String> entry : set) {
                    log.info("传入的请求头key:{},value:{}", entry.getKey(), entry.getValue());
                    httpPost.addHeader(entry.getKey(), entry.getValue());
                }
            }
            response = httpClient.execute(httpPost);
            log.info("请求返回的response:{}", response);
            HttpEntity responseEntity = response.getEntity();
            int code = response.getStatusLine().getStatusCode();
            log.info("请求返回的code:{}", code);
            if (code == 200) {
                //将响应的内容转换成字符串
                content = EntityUtils.toString(responseEntity, Charset.forName("UTF-8"));
                if (null != response) {
                    EntityUtils.consume(response.getEntity());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

        }
        return content;
    }


}
